/* loadElfLibP.h - private ELF loader library header */

/*
 * Copyright (c) 2001-2005 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use of this software
 * may be licensed only pursuant to the terms of an applicable Wind River
 * license agreement.
 */

/*
modification history
--------------------
01r,01mar05,v_r  No longer use segment_type.
01q,21feb05,dbt  Cleanup.
01p,06oct04,jn   Clean up comments
01o,18sep04,jn   Move towards shared files between host and target loaders
01n,07apr04,jn   Fix loading problems on SH
01m,04apr04,jn   Clean up - remove unused declarations and 
                 development-related comments
01l,04nov03,jn   Make sparc relocation routines available to RTP loader
01k,22oct03,jn   Make some internal elf functions public for use of rtp loader
01j,07may03,pes  PAL conditional compilation cleanup. Phase 2.
01i,17apr03,dbt  Added SIMLINUX support.
01h,04mar03,jmp  added SIMNT support.
01g,16may02,fmk  move the definition of SYM_ADRS to loadLibP.h
01f,08feb02,jn   Add comments about CHECK_FITS and SIGN_EXTEND for ARM. 
01e,09jan02,jn   Reinstate previous definition of CHECK_FITS for ARM.  Keep new
                 definition for MIPS.
01d,03jan02,jn   put back LO_VALUE macro for PPC 
01c,27nov01,pad  Added macro definitions (SIGN_EXTEND, etc.)
01b,05sep01,jn   created from loadElfLib.h@@/main/3 - moved utility macros 
                 and private type and structure definitions here
*/

#ifndef __INCloadElfLibPh
#define __INCloadElfLibPh

#ifdef __cplusplus
extern "C" {
#endif

/*
 * XXX The inclusion of elf.h is needed only so that internal ELF load
 * functions prototypes can be included here, for use by the RTP
 * loader. It should be removed when those function declarations are
 * removed from this header file. 
 */

#include "elf.h"
#include "symLib.h"
#include "private/loadLibP.h"
#include "private/loadFileLibP.h"

/* Defines */

#define CHECK_LOW14(val)        (((val & 0xffff8000) == 0) ||           \
                                 ((val & 0xffff8000) == 0xffff8000))

#define CHECK_LOW16(val)        (((val & 0xffff8000) == 0) ||           \
                                 ((val & 0xffff8000) == 0xffff8000))

#define CHECK_LOW16_STRICT(val) (((val & 0xffff0000) == 0) ||           \
                                 ((val & 0xffff0000) == 0xffff0000))

#define CHECK_LOW24(val)        (((val & 0xfe000000) == 0) ||           \
                                 ((val & 0xfe000000) == 0xfe000000))

#define INSERT(buf,value,mask) \
			((buf) = (((buf) & ~(mask)) | ((value) & (mask))))

#define LOW14_INSERT(buf,value) INSERT ((buf), (value), 0x0000fffc)

#define LOW16_VALUE(val)	((val) & 0x0000ffff)
#define LOW16_INSERT(buf,value)	INSERT ((buf), (value), 0x0000ffff)

#define LOW26_VALUE(val)	((val) & 0x03ffffff)
#define LOW26_INSERT(buf,value) INSERT ((buf), (value), 0x03ffffff)

#define LO_VALUE(val)           ((val) & 0x0000ffff)

#define HI_VALUE(val)           (((val) >> 16) & 0x0000ffff)

#define HA_VALUE(val)           ((((val) >> 16)+(((val) >> 15) & 0x1)) & 0xffff)

#define STORE_MASKED_VALUE(address, mask, value) \
    *(address) = ((*(address)) & ~(mask)) | ((value) & (mask))

/* macro to check if the alignment is a power of 2 */

#define CHECK_2_ALIGN(x)        (((x) & ((x) - 1)) == 0)

/* the binary number that is "n" 1's */

#define MASK(n)		((1 << (n)) - 1)

/* mask to get the most significant bit of a value on n bit */

#define SIGN_BIT_MASK(n) (1 << ((n) - 1))

/*
 * Sign extension macro. Sign extension replaces all higher bits in <val>
 * with copies of the most significant bit on <nBits>.
 *    <val> is the value we want to sign extend.
 *    <nBits> is the number of significant bits in <val>.
 *
 * Note: the assumption is that the storage is greater than <nBits>.
 */

#define SIGN_EXTEND(val, nBits) \
	(((MASK(nBits) & (val)) ^ SIGN_BIT_MASK(nBits)) - SIGN_BIT_MASK(nBits))

/*
 * Overflow verification macro. It checks that the signed value <val> does
 * not overflow the number of bits specified by <nBits>. The overflow for
 * signed binary numbers is defined as occuring if and only if at least one
 * of the bits beyond <nBits> is not equal to the sign bit of the value
 * truncated on <nBits>.
 *
 * The expression evaluation gives 1 when the value overflows, 0 otherwise.
 *
 * Note: the assumption is that the maximum storage is on 32 bits.
 */

#define CHECK_SIGNED_OVERFLOW(val,nBits) \
	(!(SIGN_EXTEND((val),(nBits)) == (val)))

/* Some masks */

#define RA_MSK          0x001f0000
#define GPR13_MSK       0x000d0000
#define GPR2_MSK        0x00020000

/* type definitions */

/* data structures */

typedef struct segment_info_desc /* Info about a loadable segment      */
    {
    SL_NODE	segInfoNode;	/* Point to next node in list 		    */
    SL_LIST	scnInfoList;	/* List of info nodes about sections in seg */
    UINT	type;		/* segment's type                           */
    void *      address;	/* segment's address                        */
    UINT        size;		/* segment's size                        */
    UINT        offset;		/* segment's offset in file                */
    UINT        offsetInMem;	/* seg's offset from start of mem alloc'd */
    UINT        alignment;      /* segment alignment */
    BOOL        memAllocatedByCaller; /* True iff the caller allocated mem. */
    BOOL        segHasMemFootprint; /* segment size */
    } SEGMENT_INFO_DESC;

typedef struct
    {
    UINT32 *    pLoadScnHdrIdxs;        /* loadable sections header index tbl */
    UINT32 *    pSymTabScnHdrIdxs;      /* sym table sections header idx tbl */
    UINT32 *    pRelScnHdrIdxs;         /* reloc info sections header idx tbl */
    UINT32 *    pStrTabScnHdrIdxs;      /* str table sections header idx tbl */
    } IDX_TBLS;

typedef Elf32_Sym **    SYMTBL_REFS;    /* table of pointers to symbol tables */
typedef void ***        SYMADDR_REFS;   /* table of ptrs to sym adrs tables */

/* function declarations */

extern 
#ifdef HOST
DLL_EXPORT
#endif
STATUS loadElfRelEntryRead
    (
    LOAD_MODULE_INFO *	pLoadModuleInfo,/* transient load info */
    Elf32_Rel *  pReloc,	/* Ptr on relocation structure to fill */
    BOOL	 swapIsRequired	/* Byte order must be swapped 	       */
    );

extern 
#ifdef HOST
DLL_EXPORT
#endif
STATUS loadElfRelaEntryRead
    (
    LOAD_MODULE_INFO *	pLoadModuleInfo,/* transient load info */
    Elf32_Rela * pReloc,	/* Ptr on relocation structure to fill */
    BOOL	 swapIsRequired	/* Byte order must be swapped 	       */
    );

extern STATUS loadElfSectionHeaderCheck
    (
    Elf32_Shdr * pScnHdr,		/* Pointer to a section header  */
    int		 scnHdrNum		/* Number of the section header */
    );

extern STATUS loadElfProgramHeaderTableReadAndCheck
    (
    LOAD_MODULE_INFO *	pLoadModuleInfo,/* transient load info */
    Elf32_Phdr * pProgHdrTbl,		/* Pointer to program header table */
    int          offset,                /* Offset in file to prog header tbl*/
    int		 progHdrNumber,		/* Number of header in table 	   */
    BOOL	 swapIsRequired		/* TRUE if bytes must be swapped   */
    );

extern STATUS loadElfFileHeaderReadAndCheck
    (
    LOAD_MODULE_INFO *	pLoadModuleInfo,/* transient load info */
    Elf32_Ehdr * pHdr,			/* ELF module header 		 */
    BOOL *	 swapIsRequired 	/* TRUE if bytes must be swapped */
    );

extern 
#ifdef HOST
DLL_EXPORT
#endif
STATUS elfArchReloc
    (
    BOOL         swapNeeded,    /* host only - whether to swap endianness */
    LOAD_MODULE_INFO *	pLoadModuleInfo,/* transient load info */
    Elf32_Shdr * pRelHdr,	/* Pointer to relocation section header */
    SCN_ADRS     scnAddr,       /* for relocatable files only */
    INT64        deltaBaseAddr, /* RTP base address(= file addr - real addr) */
    SYM_INFO_TBL symInfoTbl	/* Array of symbol IDs, values and types     */
    );

extern 
#ifdef HOST
DLL_EXPORT
#endif
BOOL elfArchVerify
    (
    UINT32	machType	/* Module's target arch */
    );

#ifdef __cplusplus
}
#endif

#endif /* __INCloadElfLibPh */
